package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.domain.entity.ProductUnitGroupEntity;
import com.xbongbong.saas.domain.entity.ProductUnitRateEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ServiceProjectEnum;
import com.xbongbong.saas.model.ProductUnitGroupModel;
import com.xbongbong.saas.model.ProductUnitRateModel;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 吴峰
 * @date 2020/12/17 19:12
 */
@Component
public class SaasFormHelp {

    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ProductUnitGroupModel productUnitGroupModel;
    @Resource
    private ProductUnitRateModel productUnitRateModel;

    public ProductFieldPojo getProductFieldPojo(String filePrefix,String attr, String corpid) throws XbbException {
        ProductFieldPojo productFieldPojo = new ProductFieldPojo();
        String value = paasRedisHelper.getValue(filePrefix, corpid);
        ProductFieldPojo costField = new ProductFieldPojo();
        ProductFieldPojo stockField = new ProductFieldPojo();
        ProductFieldPojo priceField = new ProductFieldPojo();
        ProductFieldPojo unitField = new ProductFieldPojo();
        if (Objects.isNull(value)) {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            if (Objects.isNull(fieldAttrEntityList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Map<String, FieldAttrEntity> fieldAttrEntityMap = fieldAttrEntityList.stream().collect(Collectors.toMap(FieldAttrEntity::getAttr, fieldAttrEntity -> fieldAttrEntity));
            List<String> setCacheAttrList = new ArrayList<>();
            setCacheAttrList.add(ProductEnum.COST.getAttr());
            setCacheAttrList.add(ProductEnum.STOCK.getAttr());
            setCacheAttrList.add(ProductEnum.PRICE.getAttr());
            setCacheAttrList.add(ProductEnum.UNIT.getAttr());
            FieldAttrEntity stockFieldAttrEntity = fieldAttrEntityMap.getOrDefault(ProductEnum.STOCK.getAttr(), new FieldAttrEntity());
            for (String cacheAttr : setCacheAttrList) {
                FieldAttrEntity fieldAttrEntity = fieldAttrEntityMap.get(cacheAttr);
                if (Objects.isNull(fieldAttrEntity)) {
                    continue;
                }
                if (Objects.equals(cacheAttr, ProductEnum.COST.getAttr())) {
                    costField.buildData(fieldAttrEntity);
                    if (Objects.equals(fieldAttrEntity.getAttr(),attr)){
                        productFieldPojo = costField;
                    }
                    paasRedisHelper.setValue(RedisPrefixConstant.PRODUCT_COST, corpid, costField, RedisTimeConstant.LONG_DURATION);
                } else if (Objects.equals(cacheAttr, ProductEnum.STOCK.getAttr())) {
                    stockField.buildData(fieldAttrEntity);
                    if (Objects.equals(fieldAttrEntity.getAttr(),attr)){
                        productFieldPojo = stockField;
                    }
                    paasRedisHelper.setValue(RedisPrefixConstant.PRODUCT_STOCK, corpid, stockField, RedisTimeConstant.LONG_DURATION);
                } else if (Objects.equals(cacheAttr, ProductEnum.PRICE.getAttr())) {
                    priceField.buildData(fieldAttrEntity);
                    if (Objects.equals(fieldAttrEntity.getAttr(),attr)){
                        productFieldPojo = priceField;
                    }
                    paasRedisHelper.setValue(RedisPrefixConstant.PRODUCT_PRICE, corpid, priceField, RedisTimeConstant.LONG_DURATION);
                } else if (Objects.equals(cacheAttr, ProductEnum.UNIT.getAttr())) {
                    unitField.buildData(fieldAttrEntity);
                    setUnitCache(unitField, fieldAttrEntity, corpid, stockFieldAttrEntity);
                    if (Objects.equals(fieldAttrEntity.getAttr(),attr)){
                        productFieldPojo = unitField;
                    }
                    paasRedisHelper.setValue(RedisPrefixConstant.PRODUCT_UNIT, corpid, unitField, RedisTimeConstant.LONG_DURATION);
                }
            }
        } else {
            productFieldPojo = JSONObject.parseObject(value, ProductFieldPojo.class);
        }
        return productFieldPojo;
    }

    private void setUnitCache(ProductFieldPojo unitField, FieldAttrEntity entity, String corpid, FieldAttrEntity stockFieldPojo) throws XbbException{
        if (Objects.equals(stockFieldPojo.getIntegerOnly(), 1)) {
            stockFieldPojo.setAccuracy(0);
        }
        unitField.setSingleItems(entity.getItems());
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<ProductUnitRateEntity> productUnitRateEntityList = productUnitRateModel.findEntitys(params);
        params.put("orderByStr", " sort DESC ");
        List<ProductUnitGroupEntity> productUnitGroupEntityList = productUnitGroupModel.findEntitys(params);
        Map<Long, List<ProductUnitRateEntity>> productUnitRateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productUnitRateEntityList.forEach(item -> {
            Long groupId = item.getGroupId();
            List<ProductUnitRateEntity> list = productUnitRateMap.getOrDefault(groupId, new ArrayList<>());
            list.add(item);
            productUnitRateMap.put(groupId, list);
        });
        List<MultiUnitItemPoJo> multiItems = new ArrayList<>();
        List<UnitItemPoJo> itemDataPoJoList = new ArrayList<>();
        productUnitGroupEntityList.forEach(item -> {
            Long groupId = item.getId();
            if (productUnitRateMap.containsKey(groupId)) {
                MultiUnitItemPoJo multiUnitItemPoJo = new MultiUnitItemPoJo();
                multiUnitItemPoJo.setText(item.getName());
                multiUnitItemPoJo.setValue(groupId);
                List<ProductUnitRateEntity> list = productUnitRateMap.get(groupId);
                List<UnitItemPoJo> itemPoJoList = new ArrayList<>(list.size());
                list.forEach(unitEntity -> {
                    if (Objects.equals(unitEntity.getIsBase(), 1)) {
                        multiUnitItemPoJo.setBaseName(unitEntity.getName());
                        multiUnitItemPoJo.setBaseValue(unitEntity.getId());
                    }
                    UnitItemPoJo unitItemPoJo = new UnitItemPoJo(groupId, unitEntity.getName(), unitEntity.getId(), unitEntity.getIsBase(), unitEntity.getRate(), unitEntity.getSort());
                    unitItemPoJo.setAccuracy(stockFieldPojo.getAccuracy());
                    itemPoJoList.add(unitItemPoJo);
                });
                multiUnitItemPoJo.setItemDataPoJoList(itemPoJoList);
                multiItems.add(multiUnitItemPoJo);
                itemDataPoJoList.addAll(itemPoJoList);
            }
        });
        unitField.setMultiItems(multiItems);
        unitField.setMultiItemDataPoJoList(itemDataPoJoList);
    }

    /**
     * 获取产品单位选项
     *
     * @param corpid
     * @return
     * @throws XbbException
     */
    public List<ItemPoJo> getProductItems(String corpid) throws XbbException{
        ProductFieldPojo productFieldPojo = getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
        List<ItemPoJo> unitItems = new ArrayList<>(productFieldPojo.getSingleItems());
        List<MultiUnitItemPoJo> multiItems = productFieldPojo.getMultiItems();
        List<ItemPoJo> multiItemsPojo = new ArrayList<>();
        try {
            BeanUtil.copyPropertiesList(multiItems, multiItemsPojo, ItemPoJo.class);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        unitItems.addAll(multiItemsPojo);
        return unitItems;
    }

    /**
     * 获取服务项目单位选项
     *
     * @param corpid
     * @return
     * @throws XbbException
     */
    public List<ItemPoJo> getServiceItems(String corpid) throws XbbException{
        try {
            PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.SERVICE_PROJECT.getCode(), corpid);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(formExplainEntity.getExplains(), null);
            String unitAttr = ServiceProjectEnum.UNIT.getAttr();
            if (MapUtils.isEmpty(explainMap) || !explainMap.containsKey(unitAttr)) {
                return new ArrayList<>();
            }
            FieldAttrEntity fieldAttrEntity = explainMap.get(unitAttr);
            return fieldAttrEntity.getItems();
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    public JSONObject formatUnit(String corpid, String productUnit) throws XbbException {
        if (StringUtil.isEmpty(productUnit)){
            return null;
        }
        ProductFieldPojo productFieldPojo = getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
        boolean isMultiUnit = StringUtil.isDigital(productUnit) && Long.parseLong(productUnit) > ProductConstant.MAX_SINGLE_UNIT_VALUE;
        JSONObject unitJson = new JSONObject();
        if (isMultiUnit) {
            List<UnitItemPoJo> multiItemDataPoJoList = productFieldPojo.getMultiItemDataPoJoList();
            Map<Long, String> unitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            multiItemDataPoJoList.forEach(item-> unitMap.put(item.getValue(), item.getText()));
            unitJson.put("value", Long.parseLong(productUnit));
            unitJson.put("text", unitMap.getOrDefault(Long.parseLong(productUnit), ""));
        } else {
            List<ItemPoJo> singleItems = productFieldPojo.getSingleItems();
            boolean isOther = false;
            for (ItemPoJo itemPoJo : singleItems){
                if (Objects.equals(itemPoJo.getValue().toString(),productUnit)){
                    unitJson.put("value",productUnit);
                    unitJson.put("text",itemPoJo.getText());
                    break;
                }
                if (!isOther){
                    isOther = Objects.equals(itemPoJo.getIsOther(),1);
                }
            }
            if (unitJson.isEmpty()){
                if (isOther){
                    unitJson.put("value",productUnit);
                    unitJson.put("text",productUnit);
                }else {
                    unitJson.put("value","");
                    unitJson.put("text","");
                }
            }
        }
        return unitJson;
    }
}
